﻿using NICWebApi.Extensions.Caching.Attributes;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// 缓存拦截器扩展
/// </summary>
public static class CacheInterceptorExtensions
{
    /// <summary>
    /// 添加缓存拦截器
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static IServiceCollection AddCacheInterceptor(this IServiceCollection services)
    {
        var allAssemblies = Utils.GetAllAssemblies();

        // 找到类中有CacheableAttribute、CacheEvictAttribute、CacheUpdateAttribute的类，并注册为动态代理
        var types = allAssemblies
            .SelectMany(a => a.GetTypes())
            .Where(u => u.IsClass &&
                u.GetMethods().Any(o =>
                    o.IsDefined(typeof(CacheableAttribute), true) ||
                    o.IsDefined(typeof(CacheEvictAttribute), true) ||
                    o.IsDefined(typeof(CacheUpdateAttribute), true)
                )
            ).ToList();

        foreach (var type in types)
        {
            // 获取继承接口
            var interfaces = type.GetInterfaces();
            // 获取可注入接口
            var canInjectInterfaces = interfaces.Where(u =>
                             u != typeof(IDisposable)
                            && u != typeof(IAsyncDisposable)
                            && allAssemblies.Contains(u.Assembly)
                            && (
                                (!type.IsGenericType && !u.IsGenericType)
                                || (type.IsGenericType && u.IsGenericType && type.GetGenericArguments().Length == u.GetGenericArguments().Length))
                            );

            foreach (var item in canInjectInterfaces)
            {
                services.Add(ServiceDescriptor.Describe(item, type, ServiceLifetime.Singleton));
            }
        }
        return services;
    }
}